<script>
import { computed, defineComponent, nextTick, ref, watch } from 'vue';
import { createNamespace, transformStyleSize } from '../utils';
import { useParent } from './helper';
import FanIcon from '../icon/icon.vue';
import DropdownItemContent from './dropdown-item-content.vue';

export default defineComponent({
  name: createNamespace('DropdownItem')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true,
  },
  components: { FanIcon, DropdownItemContent },
  props: {
    contentStyle: [String, Object],
    title: String,
    modelValue: {
      type: [Number, String],
      default: 0,
    },
    active: Boolean,
    // 设为false则不显示图标
    icon: {
      type: [String, Boolean],
      default: '',
    },
    iconSize: {
      type: [String, Number],
      default: '12px',
    },
    options: {
      type: Array,
      default: () => [],
    },
    /**
     * option-title 取值
     */
    titleProp: {
      type: String,
      default: 'text',
    },
    /**
     * modelValue 的值的来源，默认 options 数组下标
     */
    valueProp: {
      type: String,
      default: 'value',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 选项内容是否使用滚动区域
    scroll: {
      type: Boolean,
      default: false,
    },
    scrollHeight: {
      type: String,
      default: '61.8vh',
    },
    // 支付宝小程序无法通过 slots.default 自动判断，这个时候需要该属性 https://ask.dcloud.net.cn/question/136765
    // 是否自定义下拉内容，即使用插槽
    customContent: {
      type: Boolean,
      default: false,
    },
  },
  expose: ['toggle'],
  emits: ['update:modelValue', 'change', 'update:title'],
  setup(props, context) {
    const showWrapper = ref();
    const theIcon = computed(() => {
      let name = props.icon !== false ? props.icon || 'caret-down' : '';
      if (name === 'caret-down' && showWrapper.value) name = 'caret-up';
      return {
        name,
        color:
          props.active || showWrapper.value || props.icon
            ? 'currentColor'
            : 'rgba(0,0,0,0.1)',
      };
    });
    const theContentStyle = computed(() =>
      transformStyleSize(props.contentStyle),
    );

    const formatOptions = (data, titleProp, valueProp) => {
      if (!data?.length) return null;
      return data.map((a, i) => {
        return {
          title: titleProp ? a[titleProp] : a,
          value: valueProp ? a[valueProp] : i,
          children: formatOptions(a.children, titleProp, valueProp),
        };
      });
    };
    const theOptions = computed(() => {
      const { options, titleProp, valueProp } = props;
      return formatOptions(options, titleProp, valueProp) || [];
    });
    // options 为两列级联选择
    const column2 = computed(() => {
      return theOptions.value.some((a) => a.children);
    });
    const column1Active = ref(0);
    const setColumn1Active = (val) => {
      if (typeof val !== 'undefined') {
        column1Active.value = val;
        return;
      }
      if (!column2.value) return;
      const item1 = theOptions.value.find((a) => {
        if (!a.children?.length) return a.value === props.modelValue;
        return a.children.some((b) => b.value === props.modelValue);
      });
      const newVal = item1 ? item1.value : theOptions.value[0]?.value || 0;
      if (column1Active.value !== newVal) {
        column1Active.value = newVal;
      }
    };
    watch(
      () => props.modelValue,
      (val) => setColumn1Active(val),
      { immediate: true },
    );
    const column2Options = computed(() => {
      const item1 = theOptions.value.find(
        (a) => a.value === column1Active.value,
      );
      return item1?.children || [];
    });

    const { parent } = useParent('fanDropdownMenu');
    const offsetStyle = computed(() => {
      return `top:${parent.offset.value}px;`;
    });

    const animateContent = ref(false);
    const animateBg = ref(false);
    const toggle = (show = !showWrapper.value, options) => {
      if (
        props.disabled ||
        (!context.slots.default &&
          !props.customContent &&
          !theOptions.value.length) ||
        show === showWrapper.value
      ) {
        return;
      }

      showWrapper.value = show;

      if (show) {
        setColumn1Active();

        // #ifdef H5
        // TODO：小程序这段动效逻辑会导致快速连击toggle时-关闭有延迟
        animateContent.value = true;
        if (typeof options?.immediateBg === 'undefined' || !options.immediateBg)
          animateBg.value = true;
        setTimeout(() => {
          animateContent.value = false;
          animateBg.value = false;
        }, 1000 / 60);
        // #endif
      }
    };

    const emptyFunc = () => null;
    const itemClick = (opt) => {
      const val = opt.value;
      if (opt.children) {
        setColumn1Active(val);
        return;
      }
      if (val !== props.modelValue) {
        context.emit('update:modelValue', val);
        nextTick(() => {
          context.emit('update:title', opt.title);
          context.emit('change', val, opt);
        });
      }
      toggle();
    };

    return {
      theIcon,
      showWrapper,
      theContentStyle,
      offsetStyle,
      animateContent,
      animateBg,
      theOptions,
      column2,
      column2Options,
      column1Active,
      toggle,
      emptyFunc,
      itemClick,
    };
  },
});
</script>

<template>
  <div v-show="showWrapper" class="fan-dropdown-item">
    <div class="fan-dropdown-item__overlay" @click.stop="toggle(false)"></div>

    <div :style="offsetStyle" class="fan-dropdown-item__main">
      <div
        class="fan-dropdown-item__bg"
        :class="{ 'fan-dropdown--fade': animateBg }"
        @click.stop="toggle(false)"
      ></div>

      <div
        :style="theContentStyle"
        class="fan-dropdown-item__content"
        :class="{ 'fan-dropdown--slide': animateContent }"
      >
        <div v-if="column2" class="fan-flex">
          <div class="fan-dropdown-item__col1">
            <DropdownItemContent :scroll="scroll" :scroll-height="scrollHeight">
              <div
                v-for="(opt, index) in theOptions"
                :key="index"
                class="fan-dropdown-item__cell"
                :class="{
                  'fan-dropdown-item--active': column1Active === opt.value,
                }"
                @click="itemClick(opt)"
              >
                <div class="fan-flex-1 fan-ellipsis">{{ opt.title }}</div>
              </div>
            </DropdownItemContent>
          </div>
          <div class="fan-dropdown-item__col2">
            <DropdownItemContent :scroll="scroll" :scroll-height="scrollHeight">
              <div
                v-for="(opt, index) in column2Options"
                :key="index"
                class="fan-hairline--bottom fan-dropdown-item__cell"
                :class="{
                  'fan-dropdown-item--active': modelValue === opt.value,
                }"
                @click="itemClick(opt)"
              >
                <div class="fan-flex-1 fan-ellipsis">{{ opt.title }}</div>
                <FanIcon
                  v-if="modelValue === opt.value"
                  name="check-circle-fill"
                  color="var(--fan-dropdown-active-color)"
                  size="18px"
                />
              </div>
            </DropdownItemContent>
          </div>
        </div>
        <DropdownItemContent
          v-else
          :scroll="scroll"
          :scroll-height="scrollHeight"
        >
          <div
            v-for="(opt, index) in theOptions"
            :key="index"
            class="fan-hairline--bottom fan-dropdown-item__cell"
            :class="{ 'fan-dropdown-item--active': modelValue === opt.value }"
            @click="itemClick(opt)"
          >
            <div class="fan-flex-1 fan-ellipsis">{{ opt.title }}</div>
            <FanIcon
              v-if="modelValue === opt.value"
              name="check-circle-fill"
              color="var(--fan-dropdown-active-color)"
              size="18px"
            />
          </div>
        </DropdownItemContent>

        <slot />
      </div>
    </div>
  </div>
</template>

<style lang="less">
.fan-dropdown-item {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: calc(var(--fan-dropdown-menu-zindex) - 1);
  overflow: hidden;

  &__content,
  &__main {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
  }

  &__main {
    bottom: 0;
    overflow: hidden;
  }

  &__bg {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
    transition: all 0.15s linear;
  }

  &__content {
    font-size: 14px;
    color: var(--fan-black-9);
    background-color: #fff;
    transition: all 0.15s linear;
  }

  &__overlay {
    position: relative;
    width: 100%;
    height: 100%;
  }

  &__cell {
    height: 44px;
    padding: 0 12px;
    display: flex;
    align-items: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;

    &::after {
      left: 12px;
      right: 12px;
      background-color: #ebedf0;
    }
  }

  &--active {
    color: var(--fan-dropdown-active-color);
  }

  &__col1 {
    flex: 1;
    overflow: hidden;
    background-color: var(--fan-background-color);

    .fan-dropdown-item__cell {
      padding-right: 0;
    }

    .fan-dropdown-item--active {
      color: inherit;
      font-weight: 700;
      background-color: #fff;
      position: relative;

      &::before {
        content: '';
        position: absolute;
        left: 0;
        top: 50%;
        height: 38.2%;
        width: 3px;
        background: var(--fan-dropdown-active-color);
        transform: translateY(-50%);
      }
    }
  }

  &__col2 {
    flex: 2;
    overflow: hidden;

    .fan-ellipsis {
      font-weight: 700;
    }
  }
}

.fan-dropdown--fade {
  background: rgba(0, 0, 0, 0);
}

.fan-dropdown--slide {
  transform: translate3d(0, -100%, 0);
}
</style>
